package es.unex.meigas.ww.core;

import java.awt.Color;
import java.util.Random;

import org.geotools.data.DataStore;
import org.geotools.data.memory.MemoryDataStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.AttributeTypeBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Fill;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.feature.type.GeometryType;
import org.opengis.filter.FilterFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;

import es.unex.sextante.dataObjects.IVectorLayer;
import es.unex.sextante.gui.core.SextanteGUI;
import es.unex.sextante.ww.core.WWVectorLayer;
import es.unex.sextante.ww.core.WWVectorLayerFactory;
import es.unex.sextante.ww.gui.WWGUIFactory;
import gov.nasa.worldwind.WorldWindow;
import gw.layers.SimpleFeatureLayer;
import gw.util.ProjectionUtils;

public class WWSimpleFeatureVectorLayerFactory implements WWVectorLayerFactory {

	public WWSimpleFeatureVectorLayerFactory() {
		super();
	}

	public WWVectorLayer create(String sName, int iShapeType, Class<?>[] fields,
			String[] sFields, String filename, Object crs) {

		try {

			if (!(crs instanceof CoordinateReferenceSystem)) {
				crs = ProjectionUtils.getDefaultCRS();
			}

			SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
			builder.setName(sName);

			AttributeTypeBuilder attBuilder = new AttributeTypeBuilder();
			builder.add(toGeometryAttribute(iShapeType,
					(CoordinateReferenceSystem) crs,attBuilder));
			builder.setDefaultGeometry("geom");
			for (int i = 0; i < sFields.length; i++) {
				AttributeType type = attBuilder.binding(fields[i]).buildType();
				AttributeDescriptor descriptor = attBuilder.buildDescriptor(sFields[i], type);
				builder.add(descriptor);
			}
			DataStore mds = new MemoryDataStore();

			mds.createSchema(builder.buildFeatureType());

			Style s;
			if (iShapeType == IVectorLayer.SHAPE_TYPE_POLYGON){
				s = createPolygonStyle();
			}
			else if (iShapeType == IVectorLayer.SHAPE_TYPE_LINE){
				s = createLineStyle();
			}
			else{
				s = createPointStyle();
			}

			WorldWindow window = ((WWGUIFactory)SextanteGUI.getGUIFactory()).getWorldWindow();

			SimpleFeatureLayer sfLayer = new SimpleFeatureLayer(sName,
						mds.getFeatureSource(mds.getTypeNames()[0]),
						s, window,1024);

			WWVectorLayer layer = new WWVectorLayer();
			layer.create(sfLayer);

			return layer;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

    static final StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
    static final FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory(null);

    private static Style createPointStyle() {
        Style style;
        PointSymbolizer symbolizer = styleFactory.createPointSymbolizer();
        symbolizer.getGraphic().setSize(filterFactory.literal(4));
        Rule rule = styleFactory.createRule();
        rule.setSymbolizers(new Symbolizer[]{symbolizer});
        FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle();
        fts.setRules(new Rule[]{rule});
        style = styleFactory.createStyle();
        style.addFeatureTypeStyle(fts);
        return style;
    }

    private static Style createLineStyle() {
        Style style;
        LineSymbolizer symbolizer = styleFactory.createLineSymbolizer();
        SLD.setLineColour(symbolizer, Color.BLUE);
        symbolizer.getStroke().setWidth(filterFactory.literal(1));
        symbolizer.getStroke().setColor(filterFactory.literal(getRandomColorHex()));

        Rule rule = styleFactory.createRule();
        rule.setSymbolizers(new Symbolizer[]{symbolizer});
        FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle();
        fts.setRules(new Rule[]{rule});
        style = styleFactory.createStyle();
        style.addFeatureTypeStyle(fts);
        return style;
    }

    private static Style createPolygonStyle() {
        Style style;
        PolygonSymbolizer symbolizer = styleFactory.createPolygonSymbolizer();

        Fill fill = styleFactory.createFill(
                filterFactory.literal(getRandomColorHex()),
                filterFactory.literal(1.0));

        symbolizer.setFill(fill);
        Rule rule = styleFactory.createRule();
        rule.setSymbolizers(new Symbolizer[]{symbolizer});
        FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle();
        fts.setRules(new Rule[]{rule});
        style = styleFactory.createStyle();
        style.addFeatureTypeStyle(fts);
        return style;
    }

    private static String getRandomColorHex() {
        Random r = new Random();
        Color randomColor = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255), 0);
        return "#" + Integer.toHexString(randomColor.getRGB());
    }

	private GeometryDescriptor toGeometryAttribute(int shapeType,
			CoordinateReferenceSystem crs, AttributeTypeBuilder builder) {

		Class<?> s[] = { Point.class, MultiLineString.class, MultiPolygon.class };
		GeometryType buildGeometryType = builder.crs(crs).binding(s[shapeType]).buildGeometryType();
		return builder.buildDescriptor("geom", buildGeometryType);
	}

}